/**
 * ajax模块
 * */
define(['objecter', 'jsoner', 'urler'], function(objecter, jsoner, urler){
	var ajax = {
		/**
		 * @desc 发送post请求
		 * @param url <String> 访问地址
		 * @param data <Object> 数据
		 * @param success <Function> 成功回调函数
		 * */
		post: function(url, data, success){
			var options = this._meshOptions.apply(this, arguments);
			options.type = 'POST';
			this.request(options);
		},

		/**
		 * @desc 发送get请求
		 * @param url <String> 访问地址
		 * @param data <Object> 数据
		 * @param success <Function> 成功回调函数
		 * */
		'get': function(url, data, success){
			var options = this._meshOptions.apply(this, arguments);
			options.type = 'GET';
			this.request(options);
		},

		/**
		 * @desc 发送ajax请求
		 * @param options <Object> 配置
		 * {
		 *      url : <String>, 访问地址
		 *      async : <Bool>, 是否异步请求
		 *      type : <String>, 访问类型
		 *      data : <Object>, 数据
		 *      dataType : <String>, 返回值类型
		 *      success : <Function>, 功能回调函数
		 *      error : <Function>, 失败回调函数
		 *      complete : <Function> 完成回调函数
		 * }
		 * */
		request: function(options){
			options = options || {};
			options.type = (options.type || 'POST').toUpperCase();
			options.dataType = options.dataType || 'json';
			options.async = options.async === false ? false : true;
			var isTimeout = false, params = urler.formatRequestParams(options.data);

			// 创建 - 非IE6 - 第一步
			if (window.XMLHttpRequest) {
				var xhr = new XMLHttpRequest();
			} else { // IE6及其以下版本浏览器
				var xhr = new ActiveXObject('Microsoft.XMLHTTP');
			}

			// 接收 - 第三步
			xhr.onreadystatechange = function () {
				if (xhr.readyState == 4) {
					var status = xhr.status;
					// 超时检测
					if (isTimeout) {
						return false
					}
					if (status >= 200 && status < 300) {
						objecter.isFunction(options.success) && options.success(
							jsoner.parse(xhr.responseText, options.dataType), status, xhr, options
						);
					} else {
						// error可能在的值"timeout", "error", "notmodified"，"parsererror"
						objecter.isFunction(options.error) && options.error(xhr, status, options);
					}
					objecter.isFunction(options.complete) && options.complete(xhr, xhr.responseText, options);
				}
			}

			// 连接 和 发送 - 第二步
			if (/^get$/i.test(options.type)) {
				xhr.open('GET', options.url + '?' + params, options.async);
				xhr.send(null);
			} else if (/^post$/i.test(options.type)) {
				xhr.open('POST', options.url, options.async);
				//设置表单提交时的内容类型
				xhr.setRequestHeader('Content-Type', "application/x-www-form-urlencoded');
				xhr.send(params);
			}

			//超时处理
			if (options.timeout) {
				var timer = setTimeout(function () {
					if (xhr.readyState != 4) {
						isTimeout = true;
						xhr.abort();
						clearTimeout(timer);
					}
					objecter.isFunction(options.error) && options.error(xhr, 'timeout', {message: '超时'});
					//完成回调
					objecter.isFunction(options.complete) && options.complete(xhr, 'timeout', {message: '超时'});
				}, options.timeout);
			}
		},

		//jsonp请求
		jsonp: function (options) {
			var me = this, cb;
			options = options || {};
			cb = options.callback || options.jsonp || 'callback';

			//创建 script 标签并加入到页面中
			var callbackName = ('jsonp_' + Math.random()).replace(".", "");
			var oHead = document.getElementsByTagName('head')[0];
			options.data[cb] = callbackName;
			options.url = options.url || '';
			var params = urler.formatRequestParams(options.data);
			var oS = document.createElement('script'), isTimeout = false;
			oHead.appendChild(oS);

			//创建jsonp回调函数
			me[callbackName] = function (json) {
				if (isTimeout) {
					return false;
				}
				objecter.isFunction(options.success) && options.success(json);
				//完成回调
				objecter.isFunction(options.complete) && options.complete(json);
				oHead.removeChild(oS);
				clearTimeout(oS.timer);
				me[callbackName] = null;
			};

			//发送请求
			oS.src = options.url + '?' + params;

			//超时处理
			if (options.timeout) {
				oS.timer = setTimeout(function () {
					isTimeout = true;
					objecter.isFunction(options.error) && options.error(null, 'timeout', { message: '超时' });
					// 完成回调
					objecter.isFunction(options.complete) && options.complete(null, 'timeout', { message: '超时' });
					me[callbackName] = null;
					oHead.removeChild(oS);
				}, options.timeout);
			}
		},

		// 传输base64图片
		sendBase64: function(){
			var me = this;
			var input = document.querySelector("input[type=file]");
			var reader = new FileReader();
			reader.readAsDataURL(input.files[0])
			reader.onload = function (evt){
				var base64 = reader.result;
				// 重点来了 ajax在传输过程中 加号会变成空格 base64里是有加号的我不幸掉进了这个坑……
				// 把+替换成编码 %2B是加号的编码
				var newBase64 = base64.replace(/\+/g, "%2B");
				me.send({
					data : {newBase64 : newBase64}
				});
			}

			/*
			 保存
			 $base64 = $_POST['newBase64'];
			 // png格式
			 //  把头掐了
			 $image = base64_decode(str_replace('data:image/png;base64,' '', $base64));
			 file_put_contents('text.png'', $image);
			 //jpeg
			 $image = base64_decode(str_replace('data:image/jpeg;base64,' '', $base64));
			 file_put_contents('text.jpg'', $image);
			 */
		},

		/**
		 * @desc 匹配配置
		 * @param url <String> 访问地址
		 * @param data <Object> 数据
		 * @param success <Function> 成功回调函数
		 * */
		_meshOptions (url, data, success) {
			var options = {};
			// 判断是否是对象配置
			if (objecter.isPlainObject(url)) {
				options = url || options;
			} else {
				options.url = url || '';
				if (objecter.isPlainObject(data)) {
					options.data = data;
				}
			}
			options.success = objecter.isFunction(success) ? success : function(){};

			return options;
		}
	};

	return ajax;
});

/*jsonp使用

 ajax.ajax({
 url : "jsonp.php",
 dataType : "jsonp",
 jsonp: "callback",//传递给请求处理程序或页面的，用以获得jsonp回调函数名的参数名(默认为:callback)
 jsonpCallback:"jsonp_callback",//自定义的jsonp回调函数名称，默认为jQuery自动生成的随机函数名
 success : function(json){
 alert('success');
 },
 error : function(){
 alert('fail');
 }
 });

 */